feat(contracts): M002 legacy seller claims migration - #982
Conversation
Unfreezes the deployed AntseedSellerRewardsPool after M001 activates. Claims are blocked twice today: the pool has no sellerClaimPolicy, and ANTS transfers are disabled with the pool (the transfer sender) never whitelisted. - policies/AntseedLegacySellerClaimPolicy: stateless claim policy that re-derives each seller's cumulative locked ANTS from EmissionsV2/V1 state (epochs 0..lastEpoch, mirroring claimSellerEmissions), releases releaseBps (default 1538 ~ 10/65) with optional linear vesting, and returns zero for sellers the wash-trading registry has proven (or the owner flagged). - script/migrations/M002LegacySellerClaims/Install.s.sol: keyless, idempotent install. Token owner whitelists the pool on ANTSToken (skipped when transfers are enabled or already whitelisted); pool owner deploys the policy and installs it. Guards: M001 active, pool discovered via V2, lastEpoch = gate.effectiveEpoch() - 1 >= MIGRATION_EPOCH, wash registry required with code. - scripts/deployments/m002.mjs: single install phase, signers deployer + sellerRewardsPoolOwner, states ready/active/not-applicable/invalid, records 002-legacy-seller-claims and updates current.json, finalize recovery, fork test that rehearses M001 then applies M002 on top. - m001.mjs: extract rehearseM001OnFork so later migrations can layer on an activated M001 fork; ledger.mjs gains a canonicalRoot override and only regenerates chain config from the repository ledger. - Tests: policy unit tests, M002 migration tests (frozen-before proof, release payout, wash trader NothingToClaim, resume paths, no-op rerun), runner tests for M002 classification/baseline/records. - Docs: README section, M002 runbook, .env.example, CHANGELOG.
This reverts commit f1f1b43.
…/m002-legacy-seller-claims
…/m002-legacy-seller-claims
a2f8027 to
91c67a4
Compare
|
@claude review the new contract |
|
Claude finished @kotevcode's task in 3m 16s —— View job Review:
|
Summary
Adds M002, the migration that enables claims from the deployed
AntseedSellerRewardsPoolafter M001 activates.The intended release is 10% of cumulative locked rewards (1000 bps) for eligible sellers, and zero for proven wash traders. There is no vesting and no manual owner-managed eligibility list.
M002 removes both existing claim blockers:
AntseedLegacySellerClaimPolicyusing the pool owner.ANTSTokenusing the token owner, allowing payouts while general token transfers remain disabled.Claim rules and accounting
The policy uses the required, immutable wash-trading registry's
isProvenWashTrader(seller)result. Flagged sellers receive zero; their rewards remain locked.The release percentage is immutable after deployment; the installer defaults to 1000 bps (10%). There is no time-based vesting.
The policy is stateless because the pool calls it as a view. It reconstructs cumulative rewards from V2 claim flags plus V2/V1 points, scanning epochs 0 through
lastEpoch, including applicable pre-migration claims through V2. Earned points alone do not create a withdrawal entitlement.For ordinary pool sellers,
alreadyReleased = cumulativeRewards - currentLockedBalance. The policy returns the remaining lifetime allowance, capped by the actual locked balance:The pool reduces its stored locked balance after every withdrawal. Claiming again, choosing another recipient, or waiting longer cannot unlock another 10% of the same rewards.
Sellers with unclaimed legacy emissions initially receive only the allowance supported by rewards already locked. After claiming additional eligible legacy emissions into the pool, they can withdraw only the additional released share.
DIEM has zero locked rewards and cannot claim from the pool. The policy returns zero immediately for a zero locked balance; DIEM's historical direct payouts do not create an M002 withdrawal entitlement.
The policy has no owner, manual wash-trader flags, or mutable registry setter. Existing external administrative powers, including the pool owner's ability to replace the whole policy, are unchanged. Mixed future direct/locked histories remain unsupported.
Implementation
policies/AntseedLegacySellerClaimPolicy.sol: immutable configuration, registry-based wash exclusion, and cumulative release accounting.script/migrations/M002LegacySellerClaims/Install.s.sol: keyless, idempotent installation; guards M001 activation, discovers the pool through V2, deriveslastEpoch = gate.effectiveEpoch() - 1, and requires a nonzero wash registry with deployed code.scripts/deployments/m002.mjs: installation state inspection, deployment-ledger recording, crash recovery, and fork-rehearsal integration. Defaults the wash-registry address from M001's pinned configuration..env.example, and CHANGELOG.Validation — September 8, 2026
For current PR head
7ca6055f0efe34de8b185c625a98706d301d6a44:Additional local mainnet-fork validation (not yet committed or pushed)
The local fork suite, fixture, seller inventory, and detailed report are not yet part of this PR. These results exercise the current policy against actual deployed Base contracts and wash-trading state at block 51,048,693, with M002 installed only in the simulation. No mainnet transactions were sent.
All five M002-specific fork checks passed:
The real registry flags 54 sellers, including 34 existing pool depositors, who receive zero. The 48 eligible existing pool depositors have a combined initial allowance of 1,001,790.830220823917019615 ANTS. Future epoch-21 amounts remain dependent on usage before finalization.
Separate DIEM diagnostic finding: four additional local checks fail due to pre-existing downstream staker accounting, not M002 pool eligibility. Already-finalized DIEM liabilities exceed its balance by 1.580730664447246959 ANTS; including epoch 21 at frozen snapshot usage produces a 1.780069019657685820 ANTS shortfall. Payouts fail identically without M002 or the M001 registry flip. This requires separate remediation and does not give DIEM access to the locked-rewards pool. The combined focused/local run is 38 passed, 4 failed, not an all-green suite.
The direct contract-level fork checks are not a completed end-to-end deployment-CLI rehearsal: this branch's older M001 guard expects zero points policies, whereas the newer deployed configuration has one. The fork performs the authorized cutover actions directly. The current full CLI rehearsal remains to be validated against the matching M001 tooling before broadcasting.
Usage
Before broadcasting, resolve the deployment-tooling compatibility noted above, verify the intended 1000 bps configuration and wash-registry address, and follow the M001 cutover ordering, including funding any required DIEM legacy reward pots before changing emissions routing.